package com.feo.kpler

import android.content.Context
import android.media.MediaPlayer
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import android.widget.Toast
import android.widget.VideoView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.bumptech.glide.Glide
import com.feo.kpler.videocache.CacheListener
import java.io.File
import java.util.Formatter
import java.util.Locale

/**
 * 所有功能合并，包括，
 * 1、根据生命周期暂停，播放；主动暂停，主动播放
 * 2、播放进度监听，可以拖动进度
 * 3、是否缓存
 *
 */

@Suppress("CAST_NEVER_SUCCEEDS")
class FKerVideoView : LinearLayout, View.OnClickListener, DefaultLifecycleObserver, CacheListener {
    companion object {
        private const val FKER_VIDEO_DEFAULT_TIMEOUT = 3000L
    }

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)

    constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attributeSet,
        defStyleAttr
    )

    var listenerListener: FKerVideoProgressListener? = null

    // 是否使用缓存
    private var mUseCache = true

    // 是否主动暂停视频
    private var isActivePause = false

    // videoView 准备好播放
    private var mVideoPrepared = false

    //视频播放完成
    private var mVideoCompleted = false

    // 当前视频播放位置
    private var mVideoCurrentPosition = 0

    private val rlContainer: RelativeLayout

    var videoView: VideoView
    private var ivCover: ImageView

    private var mVideoUrl: String = ""

    // 加载进度
    private val progressBarLoading: ProgressBar

    // 开始按钮
    private val mStartButton: ImageView

    /**
     * 当前播放时间，进度可拖动进度，总时间
     */
    private val bottomLayout: LinearLayout
    private val mSeekBar: SeekBar
    private val tvCurrent: TextView
    private val tvTotal: TextView

    //最底部的播放进度
    private val bottomProgressBar: ProgressBar

    // 是否显示控制按钮
    private var mShowController = true

    // 当前控制器是否显示
    private var currentControllerShowed = false

    private var isRawUri = false

    private var mMediaPlayer: MediaPlayer? = null

    private var soundSwitch = true
    private var coverImgUrl: String? = null

    var videoWidth = 0
    var videoHeight = 0
    var enableLifecycleObserver = true

    init {
        inflate(context, getLayoutId(), this)



        LayoutInflater.from(context).inflate(R.layout.fk_video_layout, this)
        rlContainer = findViewById(R.id.rl_fk_container)

        videoView = findViewById(R.id.fk_player_video_view)

        ivCover = findViewById(R.id.iv_fk_cover)
        progressBarLoading = findViewById(R.id.pb_fk_loading)
        mStartButton = findViewById(R.id.iv_fk_start)

        bottomLayout = findViewById(R.id.ll_fk_layout_bottom)
        tvCurrent = findViewById(R.id.tv_fk_current)
        tvTotal = findViewById(R.id.tv_fk_total)
        mSeekBar = findViewById(R.id.sb_fk_seek_bar)
        bottomProgressBar = findViewById(R.id.pb_fk_bottom_progressbar)

        updatePlayState()
        initClickListener()
        registerLifeListener()
    }

    private fun registerLifeListener() {
        try {
            val mContext = context
            if (mContext is FragmentActivity) {
                mContext.lifecycle.addObserver(this)
            } else {
                val fragment = mContext as Fragment
                fragment.lifecycle.addObserver(this)
            }
//            Log.i("chyy", " registerListener: ${mContext}")
        } catch (e: Exception) {
            e.printStackTrace()
//            Log.i("chyy", " registerListener: ${e.message}")
        }
    }

    private fun initClickListener() {
        rlContainer.setOnClickListener(this)
        mStartButton.setOnClickListener(this)
        mSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if (!fromUser) {
                    return
                }

                val duration = videoView.duration
                val newPosition = duration * progress / 100
                mVideoCurrentPosition = newPosition
                videoView.seekTo(newPosition)
                tvCurrent.text = stringForTime(newPosition)
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
                removeCallbacks(mFadeOut)
                setProgress()
                startProgressMonitor()
                showPlayerController()
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                postDelayed(mFadeOut, FKER_VIDEO_DEFAULT_TIMEOUT)
            }
        })
    }


    fun start(url: String) {
        if (url.isBlank()) {
            Toast.makeText(context, "视频地址无效", Toast.LENGTH_SHORT).show()
            return
        }


        var mProxyURL = url
        if (mUseCache) {
            HttpMediaCacheServer.getProxy()?.let {
                it.registerCacheListener(this, url)
                mProxyURL = it.getProxyUrl(url)
            }
        }

        // 避免重复主次点击事件
        if (mProxyURL == mVideoUrl || mVideoPrepared) {
            replay()
            return
        }
        mVideoUrl = mProxyURL
        videoView.setVideoPath(mProxyURL)
        initVideoPlayerListener()

    }

    fun startUri(uri: Uri) {
        isRawUri = true
        videoView.setVideoURI(uri)
        initVideoPlayerListener()
        FKLogUtils.d("startUri")

    }

    private fun initVideoPlayerListener() {
        if (!isRawUri) {
            showLoading()
        }

        // 视频播放准备完成
        videoView.setOnPreparedListener { mediaPlayer ->

            mMediaPlayer = mediaPlayer
            mVideoPrepared = true
            videoWidth = mediaPlayer.videoWidth
            videoHeight = mediaPlayer.videoHeight
            FKLogUtils.d("setOnPreparedListener videoWidth: ${mediaPlayer.videoWidth}  height: ${mediaPlayer.videoHeight}  isPause: $isActivePause")

            if (isActivePause) {
                return@setOnPreparedListener
            }
            listenerListener?.start()
            hideLoading()
            checkSoundSwitch()
            mediaPlayer.start()


        }


        videoView.setOnInfoListener { _, what, _ ->
            when (what) {
                //媒体信息\视频渲染\开始,第一帧开始渲染
                MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START -> {
                    hideView(ivCover)
                    hideLoading()
                    updatePlayState()
                    startProgressMonitor()
                }
                //媒体信息缓冲启动 701
                MediaPlayer.MEDIA_INFO_BUFFERING_START -> {
                    showLoading()
                }
                //填充缓冲区后，MediaPlayer正在恢复播放 702
                MediaPlayer.MEDIA_INFO_BUFFERING_END -> {
                    hideLoading()
                    updatePlayState()
                }

            }

            false
        }
        // 视频播放完成
        videoView.setOnCompletionListener {
            mVideoCompleted = false
            complete()
        }

        // 视频播放监听
        videoView.setOnErrorListener { _, _, _ ->
            hideLoading()
            showPlayerController()
            false
        }

    }

    //重写此方法
    fun getLayoutId(): Int {
        return R.layout.fk_video_layout
    }

    fun setCoverUrl(url: String?, coverWidth: Int = 0, coverHeight: Int = 0) {
        this.coverImgUrl = url
        coverImgUrl?.let {
            ivCover.visibility = View.VISIBLE
            if (coverHeight > 0 && coverWidth > 0) {
                val params = ivCover.layoutParams as RelativeLayout.LayoutParams
                params.width = coverWidth
                params.height = coverHeight
                ivCover.layoutParams = params
            }
            Glide.with(context).load(it).into(ivCover)
        }
    }

    //跳转到指定播放为止
    fun seekTo(msec: Int) {
        videoView.seekTo(msec)
    }

    fun replay() {
        mVideoCompleted = false
        mVideoCurrentPosition = 0
        videoView.seekTo(0)
        videoView.start()

        checkSoundSwitch()
        updatePlayState()
        startProgressMonitor()
        try {
            removeCallbacks(mFadeOut)
            postDelayed(mFadeOut, FKER_VIDEO_DEFAULT_TIMEOUT)
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * 播放进度
     */
    private fun startProgressMonitor() {
        try {
            removeCallbacks(mShowProgress)
            post(mShowProgress)
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    fun complete() {
        removeCallbacks(mShowProgress)
        mVideoCurrentPosition = 0
        mSeekBar.progress = 0
        videoView.seekTo(0)
        tvCurrent.text = stringForTime(0)
        showPlayerController()
        mStartButton.setImageResource(R.drawable.fk_video_play_normal)
        listenerListener?.complete()
    }


    fun showController(showController: Boolean) {
        mShowController = showController

        if (showController) {
            bottomProgressBar.visibility = View.VISIBLE
            showPlayerController()
        } else {
            bottomProgressBar.visibility = View.GONE
            hidePlayerController()
        }
    }

    private fun refreshControllerStatus(showController: Boolean) {
        //全局控制不显示控制按钮
        if (!mShowController) {
            return
        }
        if (showController) {
            showPlayerController()
            bottomProgressBar.visibility = View.GONE
            postDelayed(mFadeOut, FKER_VIDEO_DEFAULT_TIMEOUT)

        } else {
            hidePlayerController()
            bottomProgressBar.visibility = View.VISIBLE
        }
    }

    private fun showLoading() {
        hidePlayerController()
        progressBarLoading.visibility = View.VISIBLE
    }

    private fun hideLoading() {
        progressBarLoading.visibility = View.GONE
    }

    private fun showPlayerController() {
        if (!mShowController) {
            return
        }
        showView(mStartButton)
        showView(bottomLayout)
    }

    private fun hidePlayerController() {

        try {
            removeCallbacks(mFadeOut)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        hideView(mStartButton)
        hideView(bottomLayout)
    }

    private fun hideView(view: View) {
        view.visibility = View.GONE
    }

    private fun showView(view: View) {
        view.visibility = View.VISIBLE
    }

    private fun updatePlayState() {
        if (videoView.isPlaying) {
            mStartButton.setImageResource(R.drawable.fk_video_pause_normal)
        } else {
            mStartButton.setImageResource(R.drawable.fk_video_play_normal)
        }
    }

    private fun stringForTime(seconds: Int): String {
        val totalSeconds = seconds / 1000
        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60 % 60
        val hours = totalSeconds / 3600
        val stringBuilder = StringBuilder()
        val mFormatter = Formatter(stringBuilder, Locale.getDefault())
        return if (hours > 0) {
            mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
        } else {
            mFormatter.format("%02d:%02d", minutes, seconds).toString()
        }

    }

    /**
     * 点击事件监听
     */

    override fun onClick(v: View) {
        when (v.id) {
            R.id.rl_fk_container -> {
                if (mShowController) {
                    currentControllerShowed = !currentControllerShowed
                    refreshControllerStatus(currentControllerShowed)
                }
            }

            R.id.iv_fk_start -> {
                if (!mVideoPrepared) {
                    start(mVideoUrl)
                    return
                }

                if (videoView.isPlaying) {
                    activePause()
                } else {
                    activeResume()
                }
            }
        }

    }

    //注册进度监听
    fun registerProgressListener(listenerListener: FKerVideoProgressListener) {
        this.listenerListener = listenerListener
    }

    /**
     * 是否使用缓存
     */
    fun setUseCache(useCache: Boolean) {
        mUseCache = useCache
    }


    /**
     * 主动调用暂停播放:主动调用暂停播放的情况下，
     * 如果触发生命周期onResume，此时不进行视频播放
     */

    fun activePause() {
        FKLogUtils.d("activePause: isPlaying ${videoView.isPlaying}")
        if (!videoView.isPlaying) {
            return
        }
        removeCallbacks(mShowProgress)
        isActivePause = true
        videoView.pause()
        hideLoading()
        updatePlayState()
        showPlayerController()
    }

    /**
     *   主动调用继续播放
     */

    fun activeResume() {
        FKLogUtils.d("activeResume: isPlaying ${videoView.isPlaying}")
        if (videoView.isPlaying) {
            return
        }
        startProgressMonitor()
        showLoading()
        isActivePause = false
        videoView.seekTo(mVideoCurrentPosition)
        videoView.start()
        updatePlayState()
        checkSoundSwitch()

    }

    /**
     * 关闭声音
     */
    fun soundOff() {
        soundSwitch = false
        mMediaPlayer?.setVolume(0f, 0f)
    }

    /**
     * 打开声音
     */
    fun soundOn() {
        soundSwitch = true
        mMediaPlayer?.setVolume(1f, 1f)
    }

    private fun checkSoundSwitch() {
        try {
            if (soundSwitch) {
                mMediaPlayer?.setVolume(1f, 1f)
            } else {
                mMediaPlayer?.setVolume(0f, 0f)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * onResume 生命周期监听
     */
    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        if (!enableLifecycleObserver) {
            return
        }
        FKLogUtils.d("onResume: $mVideoPrepared  idActivePause $isActivePause  isPlaying ${videoView.isPlaying}")
        if (!mVideoPrepared) {
            return
        }
        if (!isActivePause && !videoView.isPlaying) {
            videoView.seekTo(mVideoCurrentPosition)
            videoView.start()
            startProgressMonitor()
            updatePlayState()
            checkSoundSwitch()
        }
    }

    /**
     * onResume 生命周期监听
     */
    override fun onPause(owner: LifecycleOwner) {
        if (!enableLifecycleObserver) {
            return
        }
        FKLogUtils.d("onPause: $mVideoPrepared  idActivePause $isActivePause  isPlaying ${videoView.isPlaying}")
        super.onPause(owner)
        if (!mVideoPrepared) {
            return
        }
        if (videoView.isPlaying) {
            videoView.pause()
            removeCallbacks(mShowProgress)
            updatePlayState()
        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        videoView.suspend()

    }

    /**
     * 视频播放缓存
     */
    override fun onCacheAvailable(cacheFile: File?, url: String?, percentsAvailable: Int) {

    }

    /**
     * 隐藏播放控制器
     */
    private val mFadeOut = Runnable {
        if (!videoView.isPlaying) {
            return@Runnable
        }
        hidePlayerController()
    }

    private val mShowProgress: Runnable = object : Runnable {
        override fun run() {
            val pos: Int = setProgress()
            listenerListener?.onProgress(videoView.currentPosition, videoView.duration)
            if (videoView.isPlaying) {
                postDelayed(this, (1000 - pos % 1000).toLong())
            }
        }
    }

    private fun setProgress(): Int {
        val videoPosition = videoView.currentPosition
        if (videoPosition != 0) {
            mVideoCurrentPosition = videoPosition
        }
        if (videoView.isPlaying) {
            hideLoading()
        }
        updatePlayState()
        val duration: Int = videoView.duration


        if (duration > 0) {
            // use long to avoid overflow
            val pos = 100L * mVideoCurrentPosition / duration
            mSeekBar.progress = pos.toInt()
            if (pos >= 100 || mVideoCompleted) {
                mSeekBar.progress = 100
                complete()
            }
        }
        val percent: Int = videoView.bufferPercentage
        mSeekBar.secondaryProgress = percent * 10
        tvCurrent.text = stringForTime(mVideoCurrentPosition)
        tvTotal.text = stringForTime(duration)
        return mVideoCurrentPosition
    }


}

